# 在Python中，所有类默认继承object类,object类是顶级类或基类;其他子类叫做派生类。
class A(object):
    def a1(self):
        print('a1')

class B(object):
    def b1(self):
        print('b1')

# 单继承
class C(A):
    pass  # 表示没有任何的属性和方法

# 多继承
class D(A, B):
    pass

# 子类重写父类同名方法
# 子类和父类具有同名属性和方法，默认使用子类的同名属性和方法。
class E(A):
    def a1(self):
        print('e1')

# 在子类调用父类同名方法  方法1
# 如果定义的类名修改，这里也要修改，麻烦;代码量庞大，冗余
class F(A):
    def a1(self):
        # 如果是先调用了父类的属性和方法，父类属性会覆盖子类属性，故在调用属性前，先调用自己子类的初始化
        self.__init__()
        print('f1')
    def take_a(self):
        # 父类类名.函数(
        # 再次调用初始化的原因:这里想要调用父类的同名方法和属性，属性在init初始化位置，所以需要再次调用init
        A.__init__(self)
        A.a1(self)


# 在子类调用父类同名方法  方法2
class G(A):
    def a1(self):
        print('g1')
    def take_a(self):
        # 先初始化，再调用方法
        # 有参数形式
        # super(G, self).__init__()
        # super(G, self).a1()
        # 无参数形式
        # 注意:使用super()可以自动查找父类。调用顺序遵循_mro_类属性的顺序。比较适合单继承使用。
        super().__init__()
        super().a1()

# 多层继承
class H(D):
    pass

# 私有方法和属性
class I(object):
    def __init__(self):
        self.__name = '小鸿'
    def __i1(self):
        print('b1')
    # 获取和修改私有属性
    def get_name(self):
        return self.__name
    def set_name(self, newName):
        self.__name = newName

ob1 = C()
ob1.a1()

ob2 = D()
ob2.a1()
ob2.b1()

ob3 = E()
ob3.a1()

ob4 = F()
ob4.take_a()

ob5 = G()
ob5.take_a()

ob6 = H()
ob6.a1()
ob6.b1()

ob7 = I()
# print(ob7.__name)  # 报错，找不到
# ob7.__i1()  # 报错，找不到
print(ob7.get_name())
ob7.set_name('小美')
print(ob7.get_name())

# 查看某个类的层级继承关系
print(D.__mro__)